package concurrent.TaskQueue;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class TaskExecutors {

    private final int nThreads;
    private boolean isRunning = true;
    private final BlockingQueue<ITask> taskQueue;
    private final ExecutorService executorService;

    public TaskExecutors(int nThreads) {
        this.taskQueue = new LinkedBlockingQueue<>();
        this.nThreads = nThreads;
        this.executorService = Executors.newFixedThreadPool(nThreads);
        run();
    }

    public void exit() {
        isRunning = false;
        executorService.shutdown();
    }

    public void run() {
        for (int i = 0; i < nThreads; i++) {
            executorService.execute(() -> {
                while (isRunning) {
                    ITask iTask;
                    try {
                        iTask = taskQueue.take();
                    } catch (InterruptedException e) {
                        if (!isRunning) break;
                        continue;
                    }
                    iTask.run();
                }
            });
        }
    }

    public <T extends ITask> int add(T task) {
        if (!taskQueue.contains(task)) {
            taskQueue.add(task);
        }
        return taskQueue.size();
    }

}
